﻿// Copyright 2012 Jack Bulan (agentgeo)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace GemWorkshop.Drawing3D
{
    public class Graphics3D : IDisposable
    {
        private Graphics g;
        private Camera origin;

        private Graphics3D(Bitmap b)
        {
            g = Graphics.FromImage(b);
            origin = new Camera();
        }

        public static Graphics3D FromImage(Bitmap b)
        {
            return new Graphics3D(b);
        }

        //Converts 3D points to 2D points
        private PointF Get2D(Point3D vec, Point drawOrigin)
        {
            PointF point2D = Get2D(vec);
            return new PointF(point2D.X + drawOrigin.X, point2D.Y + drawOrigin.Y);
        }

        private PointF Get2D(Point3D vec)
        {
            PointF returnPoint = new PointF();

            float zoom = (float)Screen.PrimaryScreen.Bounds.Width / 1.5f;
            Camera tempCam = new Camera();

            tempCam.Position.X = origin.Position.X;
            tempCam.Position.Y = origin.Position.Y;
            tempCam.Position.Z = (origin.Position.X * zoom) / origin.Position.X;

            float zValue = (float)(-vec.Z - tempCam.Position.Z);

            returnPoint.X = (float)((tempCam.Position.X - vec.X) / zValue * zoom);
            returnPoint.Y = (float)((tempCam.Position.Y - vec.Y) / zValue * zoom);

            return returnPoint;
        }

        #region Implementation

        public void DrawLine(Pen pen, Point3D p1, Point3D p2)
        {
            PointF start = Get2D(p1);
            PointF end = Get2D(p2);
            g.DrawLine(pen, start, end);
        }

        public void DrawLine(Pen pen, double x, double y, double z, double x2, double y2, double z2)
        {
            DrawLine(pen, new Point3D(x, y, z), new Point3D(x2, y2, z2));
        }

        #endregion

        #region Properties

        public double OriginX
        {
            get { return origin.Position.X; }
            set { origin.Position.X = value; }
        }

        public double OriginY
        {
            get { return origin.Position.Y; }
            set { origin.Position.Y = value; }
        }

        public double OriginZ
        {
            get { return origin.Position.Z; }
            set { origin.Position.Z = value; }
        }

        #endregion

        public void Dispose()
        {
            g.Dispose();
        }
    }
}
